use std::ops::Add;
use std::marker::PhantomData;

/// 创建空枚举类型表示单位
#[derive(Debug, Clone, Copy)]
enum Inch {}
#[derive(Debug, Clone, Copy)]
enum Mm {}

/// `Length`是一个带有虚类型参数`Unit`的类型
/// 而且对于表示长度的类型，（即`f64`）而言，`Length`不是泛型
///
/// `f64`已经实现了`Clone` `Copy`trait
#[derive(Debug, Clone, Copy)]
struct Length<Unit>(f64, PhantomData<Unit>);
// `Add`trait定义了`+`运算符的行为
impl<Unit> Add for Length<Unit> {
    type Output = Self;
//     add() 返回一个含有和新的`Length`结构体
    fn add(self, rhs: Length<Unit>) -> Length<Unit>  {
    // `+`调用了针对`f64`的`add()`方法
        Length(self.0 + rhs.0, PhantomData)
    }
}
fn main() {
//     `one_foot`拥有虚类型参数`Inch`
    let one_foot: Length<Inch> = Length(12.0, PhantomData);
//     `one_meter`拥有虚类型参数`Mm`
    let one_meter: Length<Mm> = Length(1000.0, PhantomData);
    let two_feet = one_foot + one_foot;
    let two_meters = one_meter + one_meter;
    println!("one foot + one foot = {} in", two_feet.0);
    println!("one meter + one meter = {} mm", two_meters.0);
    // 无意义的运算当然会失败：
    // 编译期错误：类型不匹配。
    //let one_feter = one_foot + one_meter;
}
